
#[derive(Debug)]
enum IPVersion {
    V4(u32, u32, u32, u32),
    V6(String)
}

// 结构体字段名称一般小写
struct Color {
    r: i32,
    g: i32,
    b: i32
}

// 枚举成员一般大写或大写开关
enum Message {
    Quit,
    Move {x:i32, y:i32}, // 简单结构体
    Write(String), // 复杂类型
    ChangeColor(Color) //自定义结构体
}

#[derive(Debug)]
enum State {
    Alabama,
    Alaska,
}

enum Coin {
    Penny,
    Nickel,
    Dime,
    Quarter(State),
}

impl Message {
    fn call(&self) {
        // TODO: 这里 self 怎么用？
        println!("I'm a message.");
    }
}

#[derive(Debug)]
struct Info {
    name: Option<String>,
    addr: Option<String>,
    phone: Option<usize>,
}

impl Info {
    fn check(&self) -> bool {
        // NOTE: 这里使用元组，可以解决多重进行 if let 的判断
        if let (Some(name), Some(addr), Some(phone)) = (self.name.as_ref(), self.addr.as_ref(), self.phone) {
            println!("Info is {:?}", self);
            return true;
        }
        false
    }
}

fn main() {
    println!("examps for enum && match");

    let ip4 = IPVersion::V4(127, 0, 0, 1);
    let ip6 = IPVersion::V6(String::from("::1"));
    println!("ip4 is {:#?}", ip4);
    println!("ip6 is {:?}", ip6);

    let msg = Message::ChangeColor(Color{r :255, g: 0, b: 0});
    msg.call();
    
    println!("cents: {}", coin_cents(Coin::Quarter(State::Alaska)));

    {
        let five = Some(5);
        let six = plus_one(five);
        let none = plus_one(None);
        println!("six is {:?}, none is {:?}", six, none);
    }
    {
        // _ 通配符
        match 4 {
            1 => println!("1"),
            2 => println!("2"),
            3 => println!("3"),
            _ => ()
        }
    }

    let info = Info {
        name: Some(String::from("Melody")),
        addr: Some("shanghai".to_string()),
        phone: Some(18616080899),
    };
    info.check();
}

fn coin_cents(coin: Coin) -> u32 {
    match coin {
        Coin::Penny => 1,
        Coin::Nickel => 5,
        Coin::Dime => 10,
        Coin::Quarter(state) => {
            println!("state is {:?}", state);
            25
        },
    }
}

fn plus_one(i: Option<i32>) -> Option<i32> {
    match i {
        None => None,
        Some(x) => Some(x + 1)
    }
}